const path = require("path");

const ESLintPlugin = require('eslint-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
const PreloadWebpackPlugin = require("@vue/preload-webpack-plugin");


function myCssLoader(preProcessor){
    return[
        MiniCssExtractPlugin.loader,
        "css-loader", {
            loader: "postcss-loader",
            options: {
                postcssOptions: {
                    plugins: [
                        "postcss-preset-env", // 能解决大多数样式兼容性问题
                    ],
                },
            },
        },
        preProcessor
    ].filter(Boolean)
}

module.exports = {
    // 入口文件，相对路径
    entry: "./src/main.js",
    // 输出
    output: {
        // 要输出到的位置，绝对路径
        path: path.resolve(__dirname,"../dist"),
        // 文件名
        filename: "state/js/[name].[contenthash:8].js",
        // 给动态生成的文件命名
        chunkFilename: "state/js/chunk/[name].[contenthash:8].js",
        // 只要是使用 type:asset 的loader统一设置输出名
        // hash:10 只取10位哈希值
        // ext文件后缀名
        // query 图片文件后面携带的参数
        assetModuleFilename: "state/asset/[hash:10][ext][query]",
        // 每次打包前自动清空path对应的目录文件
        clean: true,
        // 关闭箭头函数输出
        environment: {
            arrowFunction: false
        }
    },

    // 加载器
    module: {
        rules: [
            {
                oneOf: [
                    {
                        // 用来匹配 .css 结尾的文件
                        test: /\.css$/,
                        // use 数组里面 Loader 执行顺序是从右到左
                        use: myCssLoader(),
                    },
                    {
                        test: /\.less$/i,
                        use: myCssLoader('less-loader')
                    },
                    {
                        test: /\.s[ac]ss$/i,
                        use: myCssLoader('sass-loader')
                    },
                    {
                        test: /\.(png|jpe?g|gif|webp)$/,
                        type: "asset",
                        parser: {
                            dataUrlCondition: {
                                maxSize: 18 * 1024 // 小于10kb的图片会被base64处理
                            }
                        },
                        // generator: {
                        //     // 修改图片文件的输出地址
                        //     // hash:10 只取10位哈希值
                        //     // ext图片后缀名
                        //     // query 图片文件后面携带的参数
                        //     // filename: 'state/images/[hash:10][ext][query]'
                        // }
                    },
                    {
                        test: /\.(ttf|woff2?|mp3|mp4|word)$/,
                        type: "asset/resource",
                        // generator: {
                        //     filename: 'state/resource/[hash:10][ext][query]'
                        // }
                    },
                    {
                        test: /\.m?js$/,
                        exclude: /(node_modules|bower_components)/, // 排除文件
                        use: [
                            // 在需要开启多线程运行的loader前加上 thread-loader
                            "thread-loader",
                            {
                                loader: 'babel-loader',
                                options: {
                                    cacheDirectory: true, // 开启babel编译缓存
                                    cacheCompression: false, // 缓存文件不要压缩
                                    plugins: ["@babel/plugin-transform-runtime"], // 减少代码体积
                                },
                            }
                        ]
                    }
                ]
            }
        ]
    },
    // 插件
    plugins: [
        // Eslint插件
        new ESLintPlugin({
            // 指定文件的根目录
            context:path.resolve(__dirname, "../src"),
            threads:true // 开启多线程，默认线程数是cpu核心数-1
        }),
        // 处理HTML文件
        new HtmlWebpackPlugin({
            template: path.resolve(__dirname, "../index.html"), // 使用的模板地址
            title: "学习Webpack", // 网站title
            hash:true, // 添加哈希值
        }),
        // 将CSS处理成单独文件
        new MiniCssExtractPlugin({
            filename:"state/css/[name].[contenthash:8].css",
        }),
        // 资源懒加载
        new PreloadWebpackPlugin({
            rel: "prefetch", // preload兼容性更好
            as: "script",
            // rel: 'prefetch' // prefetch兼容性更差
        })
    ],
    optimization: {
        minimize: true,
        minimizer: [
            // 压缩CSS
            new CssMinimizerPlugin({
                parallel:true,// 开启多线程
            }),
            // 当生产模式会默认开启TerserPlugin，但是我们需要进行其他配置，就要重新写了
            new TerserPlugin({
                parallel:true
            }),
            // 压缩图片
            new ImageMinimizerPlugin({
                minimizer: {
                    implementation: ImageMinimizerPlugin.imageminGenerate,
                    options: {
                        plugins: [
                            ["gifsicle", { interlaced: true }],
                            ["jpegtran", { progressive: true }],
                            ["optipng", { optimizationLevel: 5 }],
                            [
                                "svgo",
                                {
                                    plugins: [
                                        "preset-default",
                                        "prefixIds",
                                        {
                                            name: "sortAttrs",
                                            params: {
                                                xmlnsOrder: "alphabetical",
                                            },
                                        },
                                    ],
                                },
                            ],
                        ],
                    },
                },
            }),
        ],
        splitChunks: {
            chunks: "all"
        },
        // 提取runtime文件
        runtimeChunk: {
            name: (entrypoint) => `runtime~${entrypoint.name}`, // runtime文件命名规则
        },
    },
    // 模式
    mode: "production",
    devtool: "source-map"
}
